package cn.colins.consumer.controller;

import cn.colins.api.CallbackListener;
import cn.colins.api.CallbackService;
import cn.colins.api.TestService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * @program: dubbo-annotation-study
 * @description:
 * @author: colins
 * @create: 2023-05-06 14:39
 **/
@RestController
@Slf4j
public class ConsumerTestController {

    @DubboReference(check = false,protocol = "dubbo",loadbalance = "myLoadBalance",stub = "cn.colins.consumer.service.MyTestService")
    private TestService testService;

    @DubboReference(check = false)
    private CallbackService callbackService;

    @GetMapping("/test")
    public String test(String message){
        // 调用前给提供者传递参数
        RpcContext.getContext().setObjectAttachment("clientKey","server 你好！");

        String test = testService.test(message);

        // 调用后获取提供者给我的参数
        Map<String, Object> serverAttachment = RpcContext.getServerContext().getObjectAttachments();
        log.info("ContextTask clientAttachment: " + JSON.toJSON(serverAttachment));

        return test;
    }

    @GetMapping("/callbackTest")
    public String callbackTest(){
        String test = callbackService.addListener("test", new CallbackListener() {
            @Override
            public void changed(String msg) {
                log.info("callback msg : {}", msg);
            }
        });
        log.info("直接调用返回的 msg : {}", test);
        return test;
    }



    @GetMapping("/special")
    public String special(String message){
        // 调用前给提供者传递参数
        RpcContext.getContext().setObjectAttachment("clientKey","server 你好！");

        // 泛化调用 注意没有用上面引入的 testService
        GenericService genericService = buildGenericService("cn.colins.api.TestService","test1","v1");
        //传入需要调用的方法名、参数类型列表、参数值列表
        Object result = genericService.$invoke("test", new String[]{"java.lang.String"}, new Object[]{message});
        System.out.println("GenericTask Response: " + JSON.toJSONString(result));


        // 调用后获取提供者给我的参数
        Map<String, Object> serverAttachment = RpcContext.getServerContext().getObjectAttachments();
        log.info("ContextTask clientAttachment: " + JSON.toJSON(serverAttachment));

        return result.toString();
    }

    private GenericService buildGenericService(String interfaceClass, String group, String version) {
        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setInterface(interfaceClass);
        reference.setVersion(version);
        //开启泛化调用
        reference.setGeneric("true");
        reference.setTimeout(30000);
        reference.setGroup(group);
        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        try {
            return cache.get(reference);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
